home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Cafe 3
/
Visual Cafe 3.ISO
/
Vcafe
/
JFC.bin
/
MacTabbedPaneUI.java
< prev
next >
Wrap
Text File
|
1998-06-30
|
29KB
|
832 lines
/*
* @(#)MacTabbedPaneUI.java 1.13 98/02/02
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing.plaf.mac;
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import com.sun.java.swing.event.*;
import com.sun.java.swing.plaf.*;
import com.sun.java.swing.plaf.basic.BasicTabbedPaneUI;
import java.io.Serializable;
/**
* A Mac L&F implementation of TabbedPaneUI.
* <p>
* Warning: serialized objects of this class will not be compatible with
* future swing releases. The current serialization support is appropriate
* for short term storage or RMI between Swing1.0 applications. It will
* not be possible to load serialized Swing1.0 objects with future releases
* of Swing. The JDK1.2 release of Swing will be the compatibility
* baseline for the serialized form of Swing objects.
*
* @version @(#)MacTabbedPaneUI.java 1.0 11/24/97
* @author Symantec
*/
public class MacTabbedPaneUI extends BasicTabbedPaneUI
{
// Class constants
static final int TAB_TOP_SEGMENT = 0;
static final int TAB_MIDDLE_SEGMENT = 1;
static final int TAB_BOTTOM_SEGMENT = 2;
static final int TAB_LEFT_SIDE = 0;
static final int TAB_RIGHT_SIDE = 1;
static final int tabBorderSize[] = { 5, 3, 4 };
static final int tabBorderY[] = { 0, 5, 8 };
static final int tabBorderX[][] =
{// { TAB_LEFT_SIDE }, { TAB_RIGHT_SIDE }
{ 3, 8, }, // { TAB_TOP_SEGMENT }
{ 2, 11 }, // { TAB_MIDDLE_SEGMENT }
{ 0, 12 } // { TAB_BOTTOM_SEGMENT }
};
// Content area constants
static final int TOP_BORDER_HEIGHT = 3; // The part of the TAB_TOP_SEGMENT that is for the top border of the tab
static final int ROW_INDENT_SLOP = 6; // Indent each row this much
private static final int ENABLED = 0;
private static final int DISABLED = 1;
private static final int FRONT = 2;
private static final int PRESSED = 3;
private static final int TAB_BACKGROUND = 0;
private static final int TAB_FOREGROUND = 1;
private static final int TAB_HILITE1 = 2;
private static final int TAB_HILITE2 = 3;
private static final int PANE_BACKGROUND = 0;
private static final int PANE_BORDER = 1;
private static final int PANE_BEVEL_HILITE1 = 2;
private static final int PANE_BEVEL_HILITE2 = 3;
private static final int PANE_BEVEL_SHADOW1 = 4;
private static final int PANE_BEVEL_SHADOW2 = 5;
private static final int PANE_BEVEL_ACCENT1 = 6;
private static final int PANE_BEVEL_ACCENT2 = 7;
private static final int PANE_BEVEL_ACCENT3 = 8;
// Class variables
private static Insets contentBorderInsets = new Insets(3,3,3,3);
private static Color[][] tabColor = null;
private static Color[][] paneColor = null;
private static ImageIcon[] tabBorder = null;
// Instance variables
protected int numMidSegments;
protected int mouseHiliteTab = -1;
protected int paintingPaneState = ENABLED;
protected int paintingTabState = ENABLED;
protected MacTabbedPaneMouseGetter macTabbedPaneMouseGetter = new MacTabbedPaneMouseGetter();
{
super.overlay = 6;
}
// UI creation
public static ComponentUI createUI(JComponent tabbedPane) {
return new MacTabbedPaneUI();
}
// UI Installation/De-installation
public void installUI(JComponent container) {
super.installUI(container);
container.removeMouseListener(super.mouseGetter);
container.addMouseListener(macTabbedPaneMouseGetter);
container.addMouseMotionListener(macTabbedPaneMouseGetter);
}
public void uninstallUI(JComponent container) {
super.uninstallUI(container);
container.removeMouseListener(macTabbedPaneMouseGetter);
container.removeMouseMotionListener(macTabbedPaneMouseGetter);
}
protected void initPressedTabColors() {
tabColor[PRESSED][TAB_BACKGROUND] = UIManager.getColor("TabbedPane.pressedTabBackground");
tabColor[PRESSED][TAB_FOREGROUND] = UIManager.getColor("TabbedPane.pressedTabForeground");
tabColor[PRESSED][TAB_HILITE1] = UIManager.getColor("TabbedPane.pressedTabHilite1");
tabColor[PRESSED][TAB_HILITE2] = UIManager.getColor("TabbedPane.pressedTabHilite2");
}
protected void initDisabledColors() {
tabColor[DISABLED][TAB_BACKGROUND] = UIManager.getColor("TabbedPane.disabledTabBackground");
tabColor[DISABLED][TAB_FOREGROUND] = UIManager.getColor("TabbedPane.disabledTabForeground");
tabColor[DISABLED][TAB_HILITE1] = UIManager.getColor("TabbedPane.disabledTabHilite1");
tabColor[DISABLED][TAB_HILITE2] = UIManager.getColor("TabbedPane.disabledTabHilite2");
paneColor[DISABLED][PANE_BACKGROUND] = UIManager.getColor("TabbedPane.disabledPaneBackground");
paneColor[DISABLED][PANE_BORDER] = UIManager.getColor("TabbedPane.disabledPaneBorder");
paneColor[DISABLED][PANE_BEVEL_HILITE1] = UIManager.getColor("TabbedPane.disabledPaneBevelHilite1");
paneColor[DISABLED][PANE_BEVEL_HILITE2] = UIManager.getColor("TabbedPane.disabledPaneBevelHilite2");
paneColor[DISABLED][PANE_BEVEL_SHADOW1] = UIManager.getColor("TabbedPane.disabledPaneBevelShadow1");
paneColor[DISABLED][PANE_BEVEL_SHADOW2] = UIManager.getColor("TabbedPane.disabledPaneBevelShadow2");
paneColor[DISABLED][PANE_BEVEL_ACCENT1] = UIManager.getColor("TabbedPane.disabledPaneBevelAccent1");
paneColor[DISABLED][PANE_BEVEL_ACCENT2] = UIManager.getColor("TabbedPane.disabledPaneBevelAccent2");
tabBorder[DISABLED] = (ImageIcon) UIManager.getIcon("TabbedPane.disabledTabBorder");
}
protected void installDefaults(JComponent c) {
if (tabColor == null) {
tabColor = new Color[4][5];
tabColor[ENABLED][TAB_BACKGROUND] = UIManager.getColor("TabbedPane.enabledTabBackground");
tabColor[ENABLED][TAB_FOREGROUND] = UIManager.getColor("TabbedPane.enabledTabForeground");
tabColor[ENABLED][TAB_HILITE1] = UIManager.getColor("TabbedPane.enabledTabHilite1");
tabColor[ENABLED][TAB_HILITE2] = UIManager.getColor("TabbedPane.enabledTabHilite2");
tabColor[FRONT][TAB_BACKGROUND] = UIManager.getColor("TabbedPane.selectedTabBackground");
tabColor[FRONT][TAB_FOREGROUND] = UIManager.getColor("TabbedPane.selectedTabForeground");
tabColor[FRONT][TAB_HILITE1] = UIManager.getColor("TabbedPane.selectedTabHilite1");
tabColor[FRONT][TAB_HILITE2] = UIManager.getColor("TabbedPane.selectedTabHilite2");
paneColor = new Color[2][9];
paneColor[ENABLED][PANE_BACKGROUND] = UIManager.getColor("TabbedPane.enabledPaneBackground");
paneColor[ENABLED][PANE_BORDER] = UIManager.getColor("TabbedPane.enabledPaneBorder");
paneColor[ENABLED][PANE_BEVEL_HILITE1] = UIManager.getColor("TabbedPane.enabledPaneBevelHilite1");
paneColor[ENABLED][PANE_BEVEL_HILITE2] = UIManager.getColor("TabbedPane.enabledPaneBevelHilite2");
paneColor[ENABLED][PANE_BEVEL_SHADOW1] = UIManager.getColor("TabbedPane.enabledPaneBevelShadow1");
paneColor[ENABLED][PANE_BEVEL_SHADOW2] = UIManager.getColor("TabbedPane.enabledPaneBevelShadow2");
paneColor[ENABLED][PANE_BEVEL_ACCENT1] = UIManager.getColor("TabbedPane.enabledPaneBevelAccent1");
paneColor[ENABLED][PANE_BEVEL_ACCENT2] = UIManager.getColor("TabbedPane.enabledPaneBevelAccent2");
paneColor[ENABLED][PANE_BEVEL_ACCENT3] = UIManager.getColor("TabbedPane.enabledPaneBevelAccent3");
tabBorder = new ImageIcon[4];
tabBorder[ENABLED] = (ImageIcon) UIManager.getIcon("TabbedPane.enabledTabBorder");
tabBorder[FRONT] = (ImageIcon) UIManager.getIcon("TabbedPane.selectedTabBorder");
tabBorder[PRESSED] = (ImageIcon) UIManager.getIcon("TabbedPane.pressededTabBorder");
}
}
// UI Rendering
public void paint(Graphics g, JComponent container) {
JTabbedPane pane = (JTabbedPane)container;
int selectedIndex = pane.getSelectedIndex();
int tabCount = pane.getTabCount();
if (tabCount != rects.length) {
calculateLayoutInfo(pane);
}
Rectangle bounds = pane.getBounds();
Insets insets = pane.getInsets();
int height = bounds.height;
int width = bounds.width;
int tabHeight = totalTabHeight(pane,pane.getTabPlacement(), runCount);
Rectangle iconRect = new Rectangle(),
textRect = new Rectangle();
Rectangle clipRect = g.getClipBounds();
if (pane.isEnabled())
{
paintingPaneState = ENABLED;
}
else
{
if (tabColor[DISABLED][TAB_BACKGROUND] == null)
initDisabledColors();
paintingPaneState = DISABLED;
}
g.translate(insets.left, insets.top);
// Paint runs of tabs from back to front
for (int i = runCount - 1; i >= 0; i--) {
int start = tabRuns[i];
int next = tabRuns[(i == runCount - 1)? 0 : i + 1];
int end = (next != 0? next - 1: tabCount - 1);
// Paint a top border from the first tab to the right side
int rowBorderStart = rects[start].x - ROW_INDENT_SLOP - 1;
int rowBorderY = rects[start].y + rects[start].height;
paintTabRowBorder(g, rowBorderStart, rowBorderY, width - rowBorderStart);
for (int j = start; j <= end; j++) {
if (rects[j].intersects(clipRect)) {
paintTab(g, pane, rects, j, iconRect, textRect);
}
}
}
paintContentBorderTop(g, selectedIndex, tabHeight, width);
paintContentBorderSidesAndBottom(g, 0, tabHeight, width, height - tabHeight);
g.translate(-insets.left, -insets.top);
}
protected void paintTab(Graphics g, JTabbedPane pane, Rectangle[] rects,
int i, Rectangle iconRect, Rectangle textRect) {
paintingTabState = paintingPaneState;
if (paintingTabState == ENABLED)
{
if (i == pane.getSelectedIndex())
paintingTabState = FRONT;
else if (i == mouseHiliteTab)
paintingTabState = PRESSED;
}
Rectangle tabRect = rects[i];
int selectedIndex = pane.getSelectedIndex();
int tabPlacement = pane.getTabPlacement();
boolean isSelected = selectedIndex == i;
xNudge = calculateXNudge(pane,tabPlacement, i, isSelected); // broke these into separate function for easier subclassing.
yNudge = calculateYNudge(pane,tabPlacement, i, isSelected);
paintTabBackground(g, pane, tabRect.x, tabRect.y, tabRect.width, tabRect.height, isSelected);
paintTabBorder(g, pane, tabRect.x, tabRect.y, tabRect.width, tabRect.height, isSelected);
String title = pane.getTitleAt(i);
Font font = pane.getFont();
FontMetrics metrics = g.getFontMetrics(font);
Icon icon = pane.getIconAt(i);
// hardwire tabPlacement=TOP until others supported
layoutLabel(TOP, metrics, title, icon, tabRect, iconRect, textRect, isSelected );
paintText( g, pane, TOP, font, metrics, i, title, textRect, isSelected );
paintIcon( g, pane, TOP, i, icon, iconRect, isSelected );
paintFocusIndicator( g, pane, rects, i, iconRect, textRect );
}
protected int calculateYNudge( Rectangle tabRect ) {
return 0; // No nudge: the selected tab displays at the same location as the others
}
protected void paintTabRowBorder(Graphics g, int x, int y, int w) {
g.translate(x, y);
g.setColor(paneColor[paintingPaneState][PANE_BORDER]);
g.drawLine(0, 0, w, 0);
g.setColor(paneColor[paintingPaneState][PANE_BEVEL_HILITE1]);
g.drawLine(0, 1, w, 1);
g.setColor(paneColor[paintingPaneState][PANE_BEVEL_HILITE2]);
g.drawLine(0, 2, w, 2);
g.translate(-x, -y);
}
protected void paintFocusIndicator(Graphics g, JTabbedPane pane,
Rectangle[] rects, int i,
Rectangle iconRect, Rectangle textRect) {}
protected void paintContentBorderTop(Graphics g, int selectedIndex, int tabHeight, int width) {}
/**
* This function draws the etch around the content area of the pane
* note: content area means the area below the tabs
*/
protected void paintContentBorderSidesAndBottom(Graphics g, int x, int y, int w, int h) {
g.translate(x, y);
h--;
w--;
// Solid border
g.setColor(paneColor[paintingPaneState][PANE_BORDER]);
g.drawLine(0, 0, 0, h); // Left
g.drawLine(w, 0, w, h); // Right
g.drawLine(1, h, w - 1, h); // Bottom
// Left Bevel
g.setColor(paneColor[paintingPaneState][PANE_BEVEL_HILITE1]);
g.drawLine(1, 1, 1, h - 2);
g.setColor(paneColor[paintingPaneState][PANE_BEVEL_HILITE2]);
g.drawLine(2, 1, 2, h - 3);
// Right Bevel
g.setColor(paneColor[paintingPaneState][PANE_BEVEL_ACCENT1]);
g.drawLine(w - 1, 1, w - 1, 1);
g.setColor(paneColor[paintingPaneState][PANE_BEVEL_SHADOW1]);
g.drawLine(w - 1, 2, w - 1, h - 1);
g.setColor(paneColor[paintingPaneState][PANE_BEVEL_ACCENT2]);
g.drawLine(w - 2, 2, w - 2, 2);
g.setColor(paneColor[paintingPaneState][PANE_BEVEL_SHADOW2]);
g.drawLine(w - 2, 3, w - 2, h - 2);
// Bottom Bevel
g.setColor(paneColor[paintingPaneState][PANE_BEVEL_ACCENT1]);
g.drawLine(1, h - 1, 1, h - 1);
g.setColor(paneColor[paintingPaneState][PANE_BEVEL_SHADOW1]);
g.drawLine(2, h - 1, w - 2, h - 1);
g.setColor(paneColor[paintingPaneState][PANE_BEVEL_ACCENT2]);
g.drawLine(2, h - 2, 2, h - 2);
g.setColor(paneColor[paintingPaneState][PANE_BEVEL_SHADOW2]);
g.drawLine(3, h - 2, w - 3, h - 2);
g.translate(-x, -y);
}
private void paintTabBorderPixel(Graphics g, Color hilitePixelColor, Color lolitePixelColor, int x, int y, int tabWidth)
{
g.setColor(hilitePixelColor);
g.drawLine(x, y, x, y);
if (lolitePixelColor != null) g.setColor(lolitePixelColor);
g.drawLine(tabWidth - x, y, tabWidth - x, y); // Paint a mirror image
}
/**
* this function draws the border around each tab
* note that this function does not draw the background of the tab.
* that is done elsewhere
*/
protected void paintTabBorder(Graphics g, JTabbedPane pane, int x, int y, int w, int h, boolean isSelected) {
Image tabBorderImage = tabBorder[paintingTabState].getImage();
g.translate(x, y);
// Draw the TAB_TOP_SEGMENT border
int hIndent = getTopSegmentIndent();
g.drawImage(tabBorderImage,
hIndent, // dx1
0, // dy1
hIndent + tabBorderSize[TAB_TOP_SEGMENT], // dx2
tabBorderSize[TAB_TOP_SEGMENT], // dy2
tabBorderX[TAB_TOP_SEGMENT][TAB_LEFT_SIDE], // sx1
tabBorderY[TAB_TOP_SEGMENT], // sy1
tabBorderX[TAB_TOP_SEGMENT][TAB_LEFT_SIDE] + tabBorderSize[TAB_TOP_SEGMENT], // sx2
tabBorderY[TAB_TOP_SEGMENT] + tabBorderSize[TAB_TOP_SEGMENT], // sy2
pane);
int dx1 = hIndent + tabBorderSize[TAB_TOP_SEGMENT];
int dx2 = w - (hIndent + tabBorderSize[TAB_TOP_SEGMENT]);
g.setColor(paneColor[paintingPaneState][PANE_BORDER]);
g.drawLine(dx1, 0, dx2, 0);
g.setColor(tabColor[paintingTabState][TAB_HILITE1]);
g.drawLine(dx1, 1, dx2, 1);
g.setColor(tabColor[paintingTabState][TAB_HILITE2]);
g.drawLine(dx1, 2, dx2, 2);
g.drawImage(tabBorderImage,
w - (hIndent + tabBorderSize[TAB_TOP_SEGMENT]), // dx1
0, // dy1
w - hIndent, // dx2
tabBorderSize[TAB_TOP_SEGMENT], // dy2
tabBorderX[TAB_TOP_SEGMENT][TAB_RIGHT_SIDE], // sx1
tabBorderY[TAB_TOP_SEGMENT], // sy1
tabBorderX[TAB_TOP_SEGMENT][TAB_RIGHT_SIDE] + tabBorderSize[TAB_TOP_SEGMENT], // sx2
tabBorderY[TAB_TOP_SEGMENT] + tabBorderSize[TAB_TOP_SEGMENT], // sy2
pane);
int vOffset = tabBorderSize[TAB_TOP_SEGMENT];
hIndent = tabBorderX[TAB_MIDDLE_SEGMENT][TAB_LEFT_SIDE] + numMidSegments;
// Draw the TAB_MIDDLE_SEGMENT borders
for (int midSegment = 0; midSegment < numMidSegments; midSegment++)
{
hIndent--;
g.drawImage(tabBorderImage,
hIndent, // dx1
vOffset, // dy1
hIndent + tabBorderSize[TAB_MIDDLE_SEGMENT], // dx2
vOffset + tabBorderSize[TAB_MIDDLE_SEGMENT], // dy2
tabBorderX[TAB_MIDDLE_SEGMENT][TAB_LEFT_SIDE], // sx1
tabBorderY[TAB_MIDDLE_SEGMENT], // sy1
tabBorderX[TAB_MIDDLE_SEGMENT][TAB_LEFT_SIDE] + tabBorderSize[TAB_MIDDLE_SEGMENT], // sx2
tabBorderY[TAB_MIDDLE_SEGMENT] + tabBorderSize[TAB_MIDDLE_SEGMENT], // sy2
pane);
g.drawImage(tabBorderImage,
w - (hIndent + tabBorderSize[TAB_MIDDLE_SEGMENT]), // dx1
vOffset, // dy1
w - hIndent, // dx2
vOffset + tabBorderSize[TAB_MIDDLE_SEGMENT], // dy2
tabBorderX[TAB_MIDDLE_SEGMENT][TAB_RIGHT_SIDE], // sx1
tabBorderY[TAB_MIDDLE_SEGMENT], // sy1
tabBorderX[TAB_MIDDLE_SEGMENT][TAB_RIGHT_SIDE] + tabBorderSize[TAB_MIDDLE_SEGMENT], // sx2
tabBorderY[TAB_MIDDLE_SEGMENT] + tabBorderSize[TAB_MIDDLE_SEGMENT], // sy2
pane);
vOffset += tabBorderSize[TAB_MIDDLE_SEGMENT];
}
// Draw BOTTOM SEGMENT border
g.drawImage(tabBorderImage,
0, // dx1
vOffset, // dy1
tabBorderSize[TAB_BOTTOM_SEGMENT], // dx2
vOffset + tabBorderSize[TAB_BOTTOM_SEGMENT], // dy2
tabBorderX[TAB_BOTTOM_SEGMENT][TAB_LEFT_SIDE], // sx1
tabBorderY[TAB_BOTTOM_SEGMENT], // sy1
tabBorderX[TAB_BOTTOM_SEGMENT][TAB_LEFT_SIDE] + tabBorderSize[TAB_BOTTOM_SEGMENT], // sx2
tabBorderY[TAB_BOTTOM_SEGMENT] + tabBorderSize[TAB_BOTTOM_SEGMENT], // sy2
pane);
g.drawImage(tabBorderImage,
w - tabBorderSize[TAB_BOTTOM_SEGMENT], // dx1
vOffset, // dy1
w, // dx2
vOffset + tabBorderSize[TAB_BOTTOM_SEGMENT], // dy2
tabBorderX[TAB_BOTTOM_SEGMENT][TAB_RIGHT_SIDE], // sx1
tabBorderY[TAB_BOTTOM_SEGMENT], // sy1
tabBorderX[TAB_BOTTOM_SEGMENT][TAB_RIGHT_SIDE] + tabBorderSize[TAB_BOTTOM_SEGMENT], // sx2
tabBorderY[TAB_BOTTOM_SEGMENT] + tabBorderSize[TAB_BOTTOM_SEGMENT], // sy2
pane);
// Draw BOTTOM border
if (paintingTabState == FRONT)
{
vOffset += tabBorderSize[TAB_BOTTOM_SEGMENT];
paintTabBorderPixel(g, paneColor[ENABLED][PANE_BORDER], null, 0, vOffset, w);
paintTabBorderPixel(g, paneColor[ENABLED][PANE_BEVEL_HILITE1], paneColor[ENABLED][PANE_BEVEL_ACCENT3], 1, vOffset, w);
paintTabBorderPixel(g, paneColor[ENABLED][PANE_BEVEL_HILITE2], paneColor[ENABLED][PANE_BACKGROUND], 2, vOffset, w);
g.setColor(tabColor[FRONT][TAB_BACKGROUND]);
g.drawLine(3, vOffset, w-3, vOffset);
vOffset++;
paintTabBorderPixel(g, paneColor[ENABLED][PANE_BEVEL_HILITE1], null, 0, vOffset, w);
paintTabBorderPixel(g, paneColor[ENABLED][PANE_BEVEL_HILITE2], paneColor[ENABLED][PANE_BEVEL_HILITE1], 1, vOffset, w);
g.setColor(tabColor[FRONT][TAB_BACKGROUND]);
g.drawLine(2, vOffset, w-2, vOffset);
vOffset++;
paintTabBorderPixel(g, paneColor[ENABLED][PANE_BEVEL_HILITE2], null, 0, vOffset, w);
g.setColor(tabColor[FRONT][TAB_BACKGROUND]);
g.drawLine(1, vOffset, w-1, vOffset);
}
g.translate(-x, -y);
}
protected void paintTabBackground(Graphics g, JTabbedPane pane, int x, int y, int w, int h, boolean isSelected) {
g.translate(x, y);
g.setColor(tabColor[paintingTabState][TAB_BACKGROUND]);
int hIndent, vOffset, segmentWidth;
// Draw the TAB_TOP_SEGMENT background
hIndent = getTopSegmentIndent() + tabBorderSize[TAB_TOP_SEGMENT];
g.fillRect(hIndent, TOP_BORDER_HEIGHT, w - (2 * hIndent) + 1, tabBorderSize[TAB_TOP_SEGMENT] - TOP_BORDER_HEIGHT);
// Draw the MIDDLE SEGMENT backgrounds
vOffset = tabBorderSize[TAB_TOP_SEGMENT];
hIndent = tabBorderX[TAB_MIDDLE_SEGMENT][TAB_LEFT_SIDE] + numMidSegments - 1 + tabBorderSize[TAB_MIDDLE_SEGMENT];
segmentWidth = w - (2 * hIndent) + 1;
for (int midSegment = 0; midSegment < numMidSegments; midSegment++)
{
g.fillRect(hIndent, vOffset, segmentWidth, tabBorderSize[TAB_MIDDLE_SEGMENT]);
vOffset += tabBorderSize[TAB_MIDDLE_SEGMENT];
hIndent -= 1;
segmentWidth += 2;
}
// Draw BOTTOM SEGMENT background
g.fillRect(hIndent, vOffset, segmentWidth, tabBorderSize[TAB_BOTTOM_SEGMENT]);
g.translate(-x, -y);
}
protected void calculateLayoutInfo(JTabbedPane pane) {
Insets insets = pane.getInsets();
int paddingExemptRun = 0;
maxTabHeight = maxTabHeight(pane);
Font font = pane.getFont();
int maxX = pane.getSize().width - insets.right;
// int maxX = pane.getSize().width - (insets.right + 2);
int returnAt = maxX;
int tabCount = pane.getTabCount();
assureRectsCreated(tabCount);
arrangeTabs(paddingExemptRun, maxTabHeight, overlay, font,
maxX, returnAt, tabCount, pane);
padSelectedTab(pane);
}
protected void arrangeTabs(int paddingExemptRun,
int maxTabHeight, int overlay, Font font,
int maxX, int returnAt, int tabCount,
JTabbedPane pane) {
FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
Insets insets = pane.getInsets();
int i, j;
int totalX = 0;
int h = insets.top;
int sRun = -1;
runCount = 0;
// Run through tabs and partition them into runs
for (i = 0; i < tabCount; i++) {
Rectangle rect = rects[i];
if (i > 0) {
rect.x = rects[i-1].x + rects[i-1].width;
} else {
tabRuns[0] = 0;
runCount = 1;
rect.x = insets.left;
// rect.x = 2 + insets.left;
}
rect.width = tabWidth(pane, i, metrics);
// Never move a TAB down a run if it is in the first column.
// Even if there isn't enough room, moving it to a fresh
// line won't help.
//
if (rect.x != insets.left && rect.x + rect.width > returnAt) {
// if (rect.x != 2 + insets.left && rect.x + rect.width > returnAt) {
if (runCount > tabRuns.length - 1) {
expandTabRunsArray();
}
tabRuns[runCount] = i;
runCount++;
rect.x = insets.left;
// rect.x = 2 + insets.left;
}
rect.y = h;
rect.height = maxTabHeight;
// rect.y = h + selectedTabHeightPad;
// rect.height = maxTabHeight - 2;
if (i == pane.getSelectedIndex()) {
sRun = runCount;
}
}
// Rotate run array so that selected run is first
rotateTabRuns(pane,pane.getTabPlacement(),sRun);
// Step through runs from back to front to calculate
// tab y locations and to pad runs appropriately
for (i = runCount - 1; i >= 0; i--) {
int start = tabRuns[i];
int next = tabRuns[i == (runCount - 1)? 0 : i + 1];
int end = (next != 0? next - 1 : tabCount - 1);
for (j = start; j <= end; j++) {
Rectangle rect = rects[j];
rect.y = h;
// rect.y = h + selectedTabHeightPad;
rect.x += getRunIndent(i);
}
if (i != paddingExemptRun || runCount > 1) {
padRun(start, end, maxX);
}
h += (maxTabHeight - overlay);
}
}
protected int getRunIndent(int run) {
// Indent beyond where the previous border ended, plus some slop
return (getTopSegmentIndent() + tabBorderSize[TAB_TOP_SEGMENT] + ROW_INDENT_SLOP) * run + ROW_INDENT_SLOP;
}
protected void padRun(int start, int end, int maxX) {}
protected void padSelectedTab(JTabbedPane pane) {}
protected int tabWidth(JTabbedPane pane, int index, FontMetrics metrics) {
int hIndent = getTopSegmentIndent();
String title = pane.getTitleAt(index);
Icon icon = pane.getIconAt(index);
int width = 2 * hIndent;
if (icon != null)
width += icon.getIconWidth() + iconSpacingWidth;
width += metrics.stringWidth(title);
return width;
}
protected Insets getContentBorderInsets(JTabbedPane pane) {
return contentBorderInsets;
}
protected int maxTabHeight(JTabbedPane pane) {
int count = pane.getTabCount();
Font font = pane.getFont();
FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
int height = metrics.getHeight();
while (count-- > 0) {
Icon icon = pane.getIconAt(count);
if (icon != null) {
int iconHeight = icon.getIconHeight();
if (iconHeight > height) {
height = iconHeight;
}
}
}
// adjust size to contain a whole number of MIDDLE SEGMENTS
int rem = height % tabBorderSize[TAB_MIDDLE_SEGMENT];
if (rem > 0)
height += (tabBorderSize[TAB_MIDDLE_SEGMENT] - rem);
// Calculate number of MID SEGMENTS
numMidSegments = (height / tabBorderSize[TAB_MIDDLE_SEGMENT]) - 1 /* allow for the BOTTOM SEGMENT */;
maxTabHeight = tabBorderSize[TAB_TOP_SEGMENT] + (numMidSegments * tabBorderSize[TAB_MIDDLE_SEGMENT]) + tabBorderSize[TAB_BOTTOM_SEGMENT];
// maxTabHeight = height + TOP_BORDER_HEIGHT + (tabBorderSize[TAB_BOTTOM_SEGMENT] - tabBorderSize[TAB_MIDDLE_SEGMENT]);
return maxTabHeight;
}
public int tabForCoordinate(JTabbedPane pane, int x, int y) {
int theTab = super.tabForCoordinate(pane, x, y);
// If the coordinate is in a tab rectangle, see if it is
// within the 'real' area of the tab.
if (theTab >= 0)
{
int relativeX = x - rects[theTab].x;
int relativeY = y - rects[theTab].y;
int topIndent = getTopSegmentIndent();
// If the coordinate is in the right tapered area of the tab,
// Normalize it to the left for simplicity.
if (relativeX > (rects[theTab].width - topIndent))
{
relativeX = rects[theTab].width - relativeX;
}
// If the coordinate is not in the left tapered area of the tab,
// it is a valid tab coordinate
else if (relativeX > topIndent)
{
return theTab;
}
// The coordinate is in the tapered area of the tab.
// Need to do more work to determine if it is a valid tab coordinate
if (relativeY <= tabBorderSize[TAB_TOP_SEGMENT])
{
if (relativeX <= (topIndent - tabBorderSize[TAB_TOP_SEGMENT]))
theTab = -1; // Top segment region is complicated. Assume it fails.
}
else if (relativeY < maxTabHeight - tabBorderSize[TAB_BOTTOM_SEGMENT])
{
// Must be in the Mid sections. Determine which one.
int theMidSection = (relativeY - tabBorderSize[TAB_TOP_SEGMENT]) / tabBorderSize[TAB_MIDDLE_SEGMENT];
if (relativeX <= (theMidSection + tabBorderX[TAB_MIDDLE_SEGMENT][TAB_LEFT_SIDE]))
theTab = -1;
}
else
{
// Bottom segment region is complicated. Assume it succeeds
}
}
return theTab;
}
private void repaintTab(JTabbedPane pane, int tab) {
pane.repaint(rects[tab]);
}
private int getTopSegmentIndent() {
return tabBorderX[TAB_TOP_SEGMENT][TAB_LEFT_SIDE] + numMidSegments - 1;
}
class MacTabbedPaneMouseGetter implements MouseListener, MouseMotionListener, Serializable {
int mousePressedTab = -1;
//
// MouseListener methods
//
/**
* Invoked when a mouse button has been pressed on a component.
*/
public void mousePressed(MouseEvent e) {
mouseHiliteTab = -1;
JTabbedPane pane = (JTabbedPane) e.getSource();
mousePressedTab = tabForCoordinate(pane, e.getX(), e.getY());
if (mousePressedTab == pane.getSelectedIndex())
{
mousePressedTab = -1;
}
else if (mousePressedTab >= 0)
{
if (tabColor[PRESSED][TAB_BACKGROUND] == null)
initPressedTabColors();
mouseHiliteTab = mousePressedTab;
repaintTab(pane, mouseHiliteTab);
}
}
/**
* Invoked when a mouse button has been released on a component.
*/
public void mouseReleased(MouseEvent e) {
mouseHiliteTab = -1;
if (mousePressedTab >= 0)
{
JTabbedPane pane = (JTabbedPane) e.getSource();
if (mousePressedTab == tabForCoordinate(pane, e.getX(), e.getY()))
{
pane.setSelectedIndex(mousePressedTab);
}
}
}
/**
* Ignored
*/
public void mouseClicked(MouseEvent e) {}
/**
* Ignored
*/
public void mouseEntered(MouseEvent e) {}
/**
* Ignored
*/
public void mouseExited(MouseEvent e) {}
//
// MouseMotionListener methods
//
/**
* Invoked when a mouse button is pressed on a component and then
* dragged. Mouse drag events will continue to be delivered to
* the component where the first originated until the mouse button is
* released (regardless of whether the mouse position is within the
* bounds of the component).
*/
public void mouseDragged(MouseEvent e) {
if (mousePressedTab >= 0)
{
JTabbedPane pane = (JTabbedPane) e.getSource();
int newMouseHiliteTab;
if (mousePressedTab == tabForCoordinate(pane, e.getX(), e.getY()))
newMouseHiliteTab = mousePressedTab;
else
newMouseHiliteTab = -1;
if (mouseHiliteTab != newMouseHiliteTab)
{
if (mouseHiliteTab != -1)
repaintTab(pane, mouseHiliteTab);
mouseHiliteTab = newMouseHiliteTab;
if (mouseHiliteTab != -1)
repaintTab(pane, mouseHiliteTab);
}
}
}
/**
* Ignored
*/
public void mouseMoved(MouseEvent e) {}
}
}